////////////////////////////////////////////////////////////////////////////
//
//  CryEngine Source File.
//  Copyright (C), Crytek, 2010.
// -------------------------------------------------------------------------
//  File name:   CryDLCStore.h
//  Version:     v1.00
//  Created:     02/09/2010 by Paul Mikell.
//  Description: CCryDLCStore class definition
// -------------------------------------------------------------------------
//  History:
//
////////////////////////////////////////////////////////////////////////////


#ifndef __CRYDLCSTORE_H__

#define __CRYDLCSTORE_H__

#if _MSC_VER > 1000
#pragma once
#endif


#include "CryLobby.h"


#if USE_CRYLOBBY_GAMESPY


#include "ICryDLCStore.h"


#define MAX_DLCSTORE_TASKS		8
#define MAX_DLCSTORE_PARAMS		9
#define MAX_DLCSTORE_ORDERS		4

typedef uint32								CryDLCStoreTaskID;
const CryDLCStoreTaskID				CryDLCStoreInvalidTaskID = 0xFFFFFFFF;

class CCryDLCStore;
typedef _smart_ptr< CCryDLCStore > CryDLCStorePtr;

class CCryDLCStore: public CMultiThreadRefCount, public ICryDLCStore
{
public:

	CCryDLCStore( CCryLobby* pLobby, CCryLobbyService* pService );

	virtual ECryLobbyError Initialise();
	virtual ECryLobbyError Terminate();
	virtual void Tick( CTimeValue tv );

	virtual bool IsDead() const { return false; };

	// ICryDLCStore
	virtual void SetDownloadableVerifyCallback( CryDLCDownloadableVerifyCallback cb );
	virtual bool IsDownloading();
	// ~ICryDLCStore

protected:

	enum ETask
	{
		eT_CheckAvailability,
		eT_CatalogListCategories,
		eT_CatalogListItems,
		eT_CategoryGetInfo,
		eT_CategoryListItems,
		eT_ItemGetInfo,
		eT_DownloadableIsDownloaded,
		eT_UserGetPurchaseHistory,
		eT_UserStartOrder,
		eT_UserGetDownloadableAccess,
		eT_UserDownloadItem,
		eT_UserRedownloadAllMissingItems,
		eT_UserListPaymentMethods,
		eT_OrderFinalize,
		eT_OrderAdjustItemQuantity,
		eT_OrderListItems,
		eT_OrderGetInfo,
		eT_OrderGetItemInfo,
		eT_OrderSetPaymentMethod,
		eT_OrderCancel,
		eT_OrderFree,
		eT_DLCStorePlatformSpecificTask
	};

	enum ECatalogAction
	{
		eCA_None,
		eCA_Refresh,
		eCA_Use
	};

	enum ECatalogStatus
	{
		eCS_Unknown,
		eCS_Refreshing,
		eCS_RefreshFailed,
		eCS_Available,
		eCS_InUse
	};

	enum ETransactionState
	{
		eTS_NotStarted,
		eTS_AboutToStart,
		eTS_Starting,
		eTS_Started,
		eTS_Succeeded,
		eTS_Failed
	};

	struct STask
	{
		CryLobbyTaskID								lTaskID;
		ECryLobbyError								error;
		uint32												startedTask;
		uint32												subTask;
		CryDLCOrderHandle							order;
		void*													pCb;
		void*													pCbArg;
		TMemHdl												paramsMem[ MAX_DLCSTORE_PARAMS ];
		int32													paramsNum[ MAX_DLCSTORE_PARAMS ];
		bool													used;
		bool													running;
		bool													cancelled;
		bool													refreshingCatalog;
		bool													usingCatalog;
	};

	struct SItemQuantity
	{
		SItemQuantity()
		:	itemID( NULL ),
			quantity( 0 )
		{
		};

		SItemQuantity( const SItemQuantity& src )
		: itemID( src.itemID ),
			quantity( src.quantity )
		{
		};

		~SItemQuantity()
		{
		};

		const SItemQuantity& operator=( const SItemQuantity& src )
		{
			itemID = src.itemID;
			quantity = src.quantity;
			return *this;
		};

		CryDLCItemID									itemID;
		uint32												quantity;
	};

	struct SOrder
	{
		std::vector< SItemQuantity >	itemQuantities;
		CryUserID											userID;
		CryDLCPaymentMethodID					paymentMethodID;
		ETransactionState							transactionState;
		CryDLCStoreTaskID							task;
		bool													used;
	};

	virtual void									StartTaskRunning( CryDLCStoreTaskID dlcsTaskID );
	virtual void									StopTaskRunning( CryDLCStoreTaskID dlcsTaskID );
	virtual void									EndTask( CryDLCStoreTaskID dlcsTaskID );

	ECryLobbyError								StartTaskWithNewOrder( uint32 eTask, CryDLCStoreTaskID* pDLCSTaskID, CryLobbyTaskID* pLTaskID, CryUserID userID, CryDLCOrderHandle* pOrderHandle, void* pCb, void* pCbArg );
	ECryLobbyError								StartTaskWithExistingOrder( uint32 eTask, CryDLCStoreTaskID* pDLCSTaskID, CryLobbyTaskID* pLTaskID, CryDLCOrderHandle orderHandle, void* pCb, void* pCbArg );
	ECryLobbyError								StartTaskWithNoOrder( uint32 eTask, CryDLCStoreTaskID* pDLCSTaskID, CryLobbyTaskID* pLTaskID, void* pCb, void* pCbArg );
	void													StartSubTask( uint32 etask, CryDLCStoreTaskID dlcsTaskID );
	void													StartSubTask( uint32 etask, STask* pTask );
	virtual void									FreeTask( CryDLCStoreTaskID dlcsTaskID );
	virtual void									ClearTask( CryDLCStoreTaskID dlcsTaskID );
	void													CancelTask( CryLobbyTaskID lTaskID );
	ECryLobbyError								CreateTaskParamMem( CryDLCStoreTaskID dlcsTaskID, uint32 param, const void* pParamData, size_t paramDataSize );
	ECryLobbyError								CreateTaskParamMem( STask* pTask, uint32 param, const void* pParamData, size_t paramDataSize );
	void													UpdateTaskError( CryDLCStoreTaskID dlcsTaskID, ECryLobbyError error );
	static void										UpdateTaskError( STask* pTask, ECryLobbyError error );
	bool													StartTaskRefreshingCatalog( CryDLCStoreTaskID dlcsTaskID );
	bool													StopTaskRefreshingCatalog( CryDLCStoreTaskID dlcsTaskID );
	bool													StartTaskUsingCatalog( CryDLCStoreTaskID dlcsTaskID );
	bool													StopTaskUsingCatalog( CryDLCStoreTaskID dlcsTaskID );

	virtual ECryLobbyError				CreateOrderHandle( CryUserID userID, CryDLCOrderHandle* pOrderHandle );
	virtual void									FreeOrderHandle( CryDLCOrderHandle orderHandle );
	virtual void									ClearOrderHandle( CryDLCOrderHandle orderHandle );
	void													UpdateDownloadable( SCryDLCDownloadableInfo& info );

	std::vector< SCryDLCCategoryInfo >			m_catalogCategories;
	std::vector< SCryDLCItemInfo >					m_catalogItems;
	std::vector< SCryDLCDownloadableInfo >	m_downloadables;
	STask*																	m_pTasks[ MAX_DLCSTORE_TASKS ];
	SOrder*																	m_pOrders[ MAX_DLCSTORE_ORDERS ];
	CCryLobby*															m_pLobby;
	CCryLobbyService*												m_pLobbyService;
	CryDLCDownloadableVerifyCallback				m_downloadableVerifyCallback;
	uint32																	m_catalogRefreshCount;
	uint32																	m_catalogUseCount;
	ECryDLCStoreStatus											m_storeStatus;
	bool																		m_catalogRefreshing;
	bool																		m_catalogReady;

private:

	ECryLobbyError								StartTaskWithOrder( uint32 eTask, CryDLCStoreTaskID* pDLCSTaskID, CryLobbyTaskID* pLTaskID, CryDLCOrderHandle orderHandle, void* pCb, void* pCbArg );
	ECryLobbyError								StartTask( uint32 eTask, CryDLCStoreTaskID* pDLCSTaskID, CryLobbyTaskID* pLTaskID, CryDLCOrderHandle orderHandle, void* pCb, void* pCbArg );
	virtual void									CreateTask( STask* pTask, uint32 eTask, CryLobbyTaskID lTaskID, CryDLCOrderHandle orderHandle, void* pCb, void* pCbArg );
};


#endif // USE_CRYLOBBY_GAMESPY


#endif // __CRYDLCSTORE_H__
